<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 浅响应与深响应
        const obj = reactive({
            foo: { bar: 1 }
        })

        effect(() => {
            console.log(obj.foo.bar)
        })

        obj.foo.bar = 2

        function createRactive(obj, isShallow = false, isReadOnly = false) {
            return new Proxy(obj, {
                get(target, key, reciver) {
                    if (key === 'raw') {
                        return target
                    }

                    if (!isReadOnly) {
                        track(target, key)
                    }

                    const res = Reflect.get(target, key, reciver)
                    // 如果是浅响应,则直接返回原始值
                    if (isShallow) {
                        return res
                    }

                    // 得到原始值结果
                    if (typeof res === 'object' && res !== null) {
                        // 调用reactive将结果包装成响应式数据并返回
                        return isReadOnly ? readOnly(res) : reactive(res)
                    }

                    return res
                },
                set(target, key, newVal, receiver) {
                    if (isReadOnly) {
                        console.warn(`属性${key}是只读的`)
                        return true
                    }
                    const oldVal = target[key]
                    const type = Object.prototype.hasOwnProperty.call(target, key) ? 'SET' : 'ADD'
                    if (target === reactiver.raw) {
                        if (oldVal !== newVal && (oldVal === oldVal || newVal === newVal)) {
                            trigger(target, key, type)
                        }
                    }
                    return res
                },
                deleteProperty(target, key) {
                    if (isReadOnly) {
                        console.warn(`属性${key}是只读的`)
                        return true
                    }
                    const hadkey = Object.prototype.hasOwnProperty.call(target, key)
                    const res = Reflect.deleteProperty(target, key)

                    if (res && hadkey) {
                        trigger(target, key, 'DELETE')
                    }
                    return res
                }

                // ...省略其他拦截函数
            })
        }

        // reactive 函数只是对Proxy进行了一层封装
        function reactive(obj) {
            return createRactive(obj)
        }

        function shallowReactive(obj) {
            return createRactive(obj, true)
        }

        function readOnly(obj) {
            return createRactive(obj, false, true)
        }

    </script>
</body>

</html>